// Copyright Epic Games, Inc. All Rights Reserved.

#include "LyraGameplayAbility.h"
#include "LyraLogChannels.h"
#include "AbilitySystem/LyraAbilitySystemComponent.h"
#include "AbilitySystemLog.h"
#include "Player/LyraPlayerController.h"
#include "Character/LyraCharacter.h"
#include "LyraGameplayTags.h"
#include "LyraAbilityCost.h"
#include "Character/LyraHeroComponent.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "AbilitySystemGlobals.h"
#include "LyraAbilitySimpleFailureMessage.h"
#include "GameFramework/GameplayMessageSubsystem.h"
#include "AbilitySystem/LyraAbilitySourceInterface.h"
#include "AbilitySystem/LyraGameplayEffectContext.h"
#include "Physics/PhysicalMaterialWithTags.h"
#include "GameFramework/PlayerState.h"
#include "Camera/LyraCameraMode.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraGameplayAbility)


/** True if this has been instanced, always true for blueprints */

/** IsInstantiated: 如果此能力已经被实例化，则返回True，对于蓝图而言经常是True。 */

/**
 * 这是一个带参数的C++宏，在预处理阶段，最终会被替换成花括号里面的东西。 
 * 也就是说ENSURE_ABILITY_IS_INSTANTIATED_OR_RETURN(FunctionName, ReturnValue)是定义的宏，
 * 后面的都是在预处理后，宏要编程的代码。
 */
#define ENSURE_ABILITY_IS_INSTANTIATED_OR_RETURN(FunctionName, ReturnValue)																				\
{																																						\
	if (!ensure(IsInstantiated()))																														\
	{																																					\
		ABILITY_LOG(Error, TEXT("%s: " #FunctionName " cannot be called on a non-instanced ability. Check the instancing policy."), *GetPathName());	\
		return ReturnValue;																																\
	}																																					\
}

UE_DEFINE_GAMEPLAY_TAG(TAG_ABILITY_SIMPLE_FAILURE_MESSAGE, "Ability.UserFacingSimpleActivateFail.Message");
UE_DEFINE_GAMEPLAY_TAG(TAG_ABILITY_PLAY_MONTAGE_FAILURE_MESSAGE, "Ability.PlayMontageOnActivateFail.Message");

ULyraGameplayAbility::ULyraGameplayAbility(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	/** How an ability replicates state/events to everyone on the network. Replication is not required for NetExecutionPolicy. */

	/** ReplicationPolicy: 在网络中，能力怎样去复制状态或事件到每个人。对于网络执行策略而言复制是非须的。 */
	ReplicationPolicy = EGameplayAbilityReplicationPolicy::ReplicateNo;

	/** How the ability is instanced when executed. This limits what an ability can do in its implementation. */

	/** InstancingPolicy: 当能力被执行的时候如何初始化。这能限制在它实现时能力能做什么。 */
	InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;

	/** How does an ability execute on the network. Does a client "ask and predict", "ask and wait", "don't ask (just do it)". */

	/** NetExecutionPolicy: 在网络中怎样执行能力。像客户端“请求和预测”、“请求和等待”、“不请求(仅执行)”。 */
	NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::LocalPredicted;

	/** What protections does this ability have? Should the client be allowed to request changes to the execution of the ability? */

	/** NetSecurityPolicy: 能力有哪些保护措施？应该客户端被允许去请求改变执行的能力？ */
	NetSecurityPolicy = EGameplayAbilityNetSecurityPolicy::ClientOrServer;

	// Defines how this ability is meant to activate.

	// 定义能力怎样去激活是意义的。
	ActivationPolicy = ELyraAbilityActivationPolicy::OnInputTriggered;

	// Defines the relationship between this ability activating and other abilities activating.

  // 定义能力激活和其他能力激活之间的关系。
	ActivationGroup = ELyraAbilityActivationGroup::Independent;

	// If true, extra information should be logged when this ability is canceled. This is temporary, used for tracking a bug.

  // 如果为True，额外的信息应该被记录，当能力被取消时。这是临时的，用于去跟踪bug。
	bLogCancelation = false;

	// Current camera mode set by the ability.

  // 被能力设置的当前摄像机模式。
	ActiveCameraMode = nullptr;
}

/** 从角色信息中获取ASC。 */

ULyraAbilitySystemComponent* ULyraGameplayAbility::GetLyraAbilitySystemComponentFromActorInfo() const
{
	/**
	 * mutable const FGameplayAbilityActorInfo* CurrentActorInfo;
	 * 这种用法表示，不能修改CurrentActorInfo指向的对象的内容，但是能修改CurrentActorInfo指针的指向。
	 */

	/**
	*  This is shared, cached information about the thing using us
	*	 E.g, Actor*, MovementComponent*, AnimInstance, etc.
	*	 This is hopefully allocated once per actor and shared by many abilities.
	*	 The actual struct may be overridden per game to include game specific data.
	*	 (E.g, child classes may want to cast to FMyGameAbilityActorInfo)
	*/

	/**
	 * CurrentActorInfo: 
	 * 这是共享的，缓存我们使用的东西的信息。
	 * 例如：Actor指针、MovementComponent指针、AnimInstance实例等。
	 * 希望每个角色仅分配一次这个（资源或对象），并且能被多种能力所共享。 
	 * 这实际的结构体也许会被覆盖在每局游戏去包括游戏具体数据。
	 * (例如：子类可能想要去转换成FMyGameAbilityActorInfo)。
	 */
	return (CurrentActorInfo ? Cast<ULyraAbilitySystemComponent>(CurrentActorInfo->AbilitySystemComponent.Get()) : nullptr);
}

ALyraPlayerController* ULyraGameplayAbility::GetLyraPlayerControllerFromActorInfo() const
{
	return (CurrentActorInfo ? Cast<ALyraPlayerController>(CurrentActorInfo->PlayerController.Get()) : nullptr);
}

AController* ULyraGameplayAbility::GetControllerFromActorInfo() const
{
	/**
	 * 突然明白之前看Aura获取玩家控制器的方式了；
	 * 首先是直接从当前玩家信息中直接获取，如果没获取到，就去所有者链表中逐级获取。
	 */
	if (CurrentActorInfo)
	{
		if (AController* PC = CurrentActorInfo->PlayerController.Get())
		{
			return PC;
		}

		// Look for a player controller or pawn in the owner chain.

		// 搜索玩家控制器或Pawn在自己的链表中。

		/**
		 * 这里是使用GetOwner()来实现逐级获取Actor的方式，下面的就看看就好，不详细说明。
		 */
		AActor* TestActor = CurrentActorInfo->OwnerActor.Get();

		while (TestActor)
		{
			if (AController* C = Cast<AController>(TestActor))
			{
				return C;
			}

			if (APawn* Pawn = Cast<APawn>(TestActor))
			{
				return Pawn->GetController();
			}
			/**
			 * Owner of this Actor, used primarily for replication (bNetUseOwnerRelevancy & bOnlyRelevantToOwner) and visibility (PrimitiveComponent bOwnerNoSee and bOnlyOwnerSee)
			 * @see SetOwner(), GetOwner()
			 */

			/**
			 * GetOwner: 
			 * 此Actor的所有者，用于初始化复制和显示。
			 */
			TestActor = TestActor->GetOwner();
		}
	}

	return nullptr;
}

ALyraCharacter* ULyraGameplayAbility::GetLyraCharacterFromActorInfo() const
{
	return (CurrentActorInfo ? Cast<ALyraCharacter>(CurrentActorInfo->AvatarActor.Get()) : nullptr);
}

ULyraHeroComponent* ULyraGameplayAbility::GetHeroComponentFromActorInfo() const
{
	return (CurrentActorInfo ? ULyraHeroComponent::FindHeroComponent(CurrentActorInfo->AvatarActor.Get()) : nullptr);
}

void ULyraGameplayAbility::NativeOnAbilityFailedToActivate(const FGameplayTagContainer& FailedReason) const
{
	bool bSimpleFailureFound = false;
	for (FGameplayTag Reason : FailedReason)
	{
		if (!bSimpleFailureFound)
		{
			/**
			 * Find: 
			 * FORCEINLINE const ValueType* Find(KeyConstPointerType Key) const
			 * {
			 *		return const_cast<TMapBase*>(this)->Find(Key);
			 * }
			 * 这里是将映射值转换为可修改的指针返回。
			 */
			if (const FText* pUserFacingMessage = FailureTagToUserFacingMessages.Find(Reason))
			{
				FLyraAbilitySimpleFailureMessage Message;
				Message.PlayerController = GetActorInfo().PlayerController.Get();
				Message.FailureTags = FailedReason;
				Message.UserFacingReason = *pUserFacingMessage;
				/**
				 * This system allows event raisers and listeners to register for messages without
				 * having to know about each other directly, though they must agree on the format
				 * of the message (as a USTRUCT() type).
				 *
				 *
				 * You can get to the message router from the game instance:
				 *    UGameInstance::GetSubsystem<UGameplayMessageSubsystem>(GameInstance)
				 * or directly from anything that has a route to a world:
				 *    UGameplayMessageSubsystem::Get(WorldContextObject)
				 *
				 * Note that call order when there are multiple listeners for the same channel is
				 * not guaranteed and can change over time!
				 */

				/**
				 * 这个系统允许事件发起者和监听者去注册，不需要直接地知道彼此的消息，但是它们必须知道消息的格式(作为USTRUCT()类型)。
				 */
				UGameplayMessageSubsystem& MessageSystem = UGameplayMessageSubsystem::Get(GetWorld());
				MessageSystem.BroadcastMessage(TAG_ABILITY_SIMPLE_FAILURE_MESSAGE, Message);
				bSimpleFailureFound = true;
			}
		}

		/**
		* FindRef:
		 * FORCEINLINE ValueType FindRef(KeyConstPointerType Key) const
		 * {
		 *	if (const auto* Pair = Pairs.Find(Key))
		 *	{
		 *		return Pair->Value;
		 *	}
		 *
		 *	return ValueType();
		 * }
		 * 这里是将存储的映射值直接返回。
		*/
		if (UAnimMontage* pMontage = FailureTagToAnimMontage.FindRef(Reason))
		{
			FLyraAbilityMontageFailureMessage Message;
			Message.PlayerController = GetActorInfo().PlayerController.Get();
			Message.FailureTags = FailedReason;
			Message.FailureMontage = pMontage;

			UGameplayMessageSubsystem& MessageSystem = UGameplayMessageSubsystem::Get(GetWorld());
			MessageSystem.BroadcastMessage(TAG_ABILITY_PLAY_MONTAGE_FAILURE_MESSAGE, Message);
		}
	}
}

bool ULyraGameplayAbility::CanActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayTagContainer* SourceTags, const FGameplayTagContainer* TargetTags, FGameplayTagContainer* OptionalRelevantTags) const
{
	if (!ActorInfo || !ActorInfo->AbilitySystemComponent.IsValid())
	{
		return false;
	}
	/** Returns true if this ability can be activated right now. Has no side effects */

	/** CanActivateAbility: 如果能力能立即被激活，则返回True。没有副作用。 */
	if (!Super::CanActivateAbility(Handle, ActorInfo, SourceTags, TargetTags, OptionalRelevantTags))
	{
		return false;
	}

	//@TODO Possibly remove after setting up tag relationships

	//@TODO 尽可能移除在设置标签关联之后。
	ULyraAbilitySystemComponent* LyraASC = CastChecked<ULyraAbilitySystemComponent>(ActorInfo->AbilitySystemComponent.Get());

	/** IsActivationGroupBlocked: 是否是激活组阻塞。 */
	if (LyraASC->IsActivationGroupBlocked(ActivationGroup))
	{
		if (OptionalRelevantTags)
		{
			OptionalRelevantTags->AddTag(LyraGameplayTags::Ability_ActivateFail_ActivationGroup);
		}
		return false;
	}

	return true;
}

void ULyraGameplayAbility::SetCanBeCanceled(bool bCanBeCanceled)
{
	// The ability can not block canceling if it's replaceable.

	// 如果是可替换的，这个能力不能被阻塞取消。
	if (!bCanBeCanceled && (ActivationGroup == ELyraAbilityActivationGroup::Exclusive_Replaceable))
	{
		UE_LOG(LogLyraAbilitySystem, Error, TEXT("SetCanBeCanceled: Ability [%s] can not block canceling because its activation group is replaceable."), *GetName());
		return;
	}
	/** Sets whether the ability should ignore cancel requests. Only valid on instanced abilities */

	/** SetCanBeCanceled: 设置能力是否被忽略取消请求。仅在实例化能力有效。 */
	Super::SetCanBeCanceled(bCanBeCanceled);
}

void ULyraGameplayAbility::OnGiveAbility(const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilitySpec& Spec)
{
	/** Called when the ability is given to an AbilitySystemComponent */

	/** OnGiveAbility: 当能力被基于给ASC时调用。 */
	Super::OnGiveAbility(ActorInfo, Spec);

	K2_OnAbilityAdded();

	TryActivateAbilityOnSpawn(ActorInfo, Spec);
}

void ULyraGameplayAbility::OnRemoveAbility(const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilitySpec& Spec)
{
	K2_OnAbilityRemoved();
	/** Called when the ability is removed from an AbilitySystemComponent */

	/** OnRemoveAbility: 当能力从ASC上被移除时调用。 */
	Super::OnRemoveAbility(ActorInfo, Spec);
}

void ULyraGameplayAbility::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
	/** Actually activate ability, do not call this directly */

	/** ActivateAbility: 实际激活能力，不能直接调用。 */
	Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);
}

void ULyraGameplayAbility::EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled)
{
	ClearCameraMode();
	/** Native function, called if an ability ends normally or abnormally. If bReplicate is set to true, try to replicate the ending to the client/server */

	/** EndAbility: 原始函数，如果能力被正常或非正常取消时调用。如果bReplicate被设置为True，尝试在结束时去复制到客户端或服务端。 */
	Super::EndAbility(Handle, ActorInfo, ActivationInfo, bReplicateEndAbility, bWasCancelled);
}

bool ULyraGameplayAbility::CheckCost(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, OUT FGameplayTagContainer* OptionalRelevantTags) const
{
	/** Checks cost. returns true if we can pay for the ability. False if not */

	/** CheckCost: 检查消耗。如果我们能支付这个能力，则返回True。如果不能则返回False。 */
	if (!Super::CheckCost(Handle, ActorInfo, OptionalRelevantTags) || !ActorInfo)
	{
		return false;
	}

	// Verify we can afford any additional costs

	// 证实我们支付任意额外消费。
	for (TObjectPtr<ULyraAbilityCost> AdditionalCost : AdditionalCosts)
	{
		if (AdditionalCost != nullptr)
		{
			/**
			 * Checks if we can afford this cost.
			 *
			 * A failure reason tag can be added to OptionalRelevantTags (if non-null), which can be queried
			 * elsewhere to determine how to provide user feedback (e.g., a clicking noise if a weapon is out of ammo)
			 *
			 * Ability and ActorInfo are guaranteed to be non-null on entry, but OptionalRelevantTags can be nullptr.
			 *
			 * @return true if we can pay for the ability, false otherwise.
			 */

			/**
			 * CheckCost: 检查我们是否能支付这个消耗。
			 * 
			 * 可以将失败原因标签添加到OptionalRelevantTags(如果该指针不为空)，之后可在其他地方查询此标签，以确定如何向用户提供反馈(例如，若武器弹药耗尽，则发出点击噪音)。
			 * 进入(该函数或代码段)时，Ability和ActorInfo保证不为空，但OptionalRelevantTags可能为空指针。
			 */
			if (!AdditionalCost->CheckCost(this, Handle, ActorInfo, /*inout*/ OptionalRelevantTags))
			{
				return false;
			}
		}
	}

	return true;
}

void ULyraGameplayAbility::ApplyCost(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo) const
{
	/** Applies the ability's cost to the target */

	/** ApplyCost: 应用能力消耗到目标节点。 */
	Super::ApplyCost(Handle, ActorInfo, ActivationInfo);

	check(ActorInfo);

	// Used to determine if the ability actually hit a target (as some costs are only spent on successful attempts)

	// 用于确定能力是否实际地碰撞节点。(因为一下消耗仅在成功尝试之后花费)。
	auto DetermineIfAbilityHitTarget = [&]()
	{
		/** Returns true if the owning actor has net authority */

		/** IsNetAuthority: 仅在所属者Actor是网络权威时返回True。 */
		if (ActorInfo->IsNetAuthority())
		{
			if (ULyraAbilitySystemComponent* ASC = Cast<ULyraAbilitySystemComponent>(ActorInfo->AbilitySystemComponent.Get()))
			{
				FGameplayAbilityTargetDataHandle TargetData;
				ASC->GetAbilityTargetData(Handle, ActivationInfo, TargetData);
				for (int32 TargetDataIdx = 0; TargetDataIdx < TargetData.Data.Num(); ++TargetDataIdx)
				{
					/** Returns true if the target data has a hit result */

					/** TargetDataHasHitResult: 如果节点数据有碰撞结果，则返回True。 */
					if (UAbilitySystemBlueprintLibrary::TargetDataHasHitResult(TargetData, TargetDataIdx))
					{
						return true;
					}
				}
			}
		}

		return false;
	};

	// Pay any additional costs

	// 支付任意额外消费。
	bool bAbilityHitTarget = false;
	bool bHasDeterminedIfAbilityHitTarget = false;
	for (TObjectPtr<ULyraAbilityCost> AdditionalCost : AdditionalCosts)
	{
		if (AdditionalCost != nullptr)
		{
			/** If true, this cost should only be applied if this ability hits successfully */

			/** ShouldOnlyApplyCostOnHit: 如果为True，这个消耗仅在能力成功地碰撞时支付。 */
			if (AdditionalCost->ShouldOnlyApplyCostOnHit())
			{
				if (!bHasDeterminedIfAbilityHitTarget)
				{
					bAbilityHitTarget = DetermineIfAbilityHitTarget();
					bHasDeterminedIfAbilityHitTarget = true;
				}

				if (!bAbilityHitTarget)
				{
					continue;
				}
			}

			AdditionalCost->ApplyCost(this, Handle, ActorInfo, ActivationInfo);
		}
	}
}

FGameplayEffectContextHandle ULyraGameplayAbility::MakeEffectContext(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo) const
{
	/** Returns an effect context, given a specified actor info */

	/** MakeEffectContext: 给定具体Actor信息，返回效果上下文。 */
	FGameplayEffectContextHandle ContextHandle = Super::MakeEffectContext(Handle, ActorInfo);
	/** Returns the wrapped FLyraGameplayEffectContext from the handle, or nullptr if it doesn't exist or is the wrong type */

	/** ExtractEffectContext: 从句柄中返回封装的FLyraGameplayEffectContext，或者如果是不存在或错误类型则返回nullptr。 */
	FLyraGameplayEffectContext* EffectContext = FLyraGameplayEffectContext::ExtractEffectContext(ContextHandle);
	check(EffectContext);

	check(ActorInfo);

	AActor* EffectCauser = nullptr;
	const ILyraAbilitySourceInterface* AbilitySource = nullptr;
	float SourceLevel = 0.0f;
	GetAbilitySource(Handle, ActorInfo, /*out*/ SourceLevel, /*out*/ AbilitySource, /*out*/ EffectCauser);

	UObject* SourceObject = GetSourceObject(Handle, ActorInfo);

	AActor* Instigator = ActorInfo ? ActorInfo->OwnerActor.Get() : nullptr;
	/** Sets the object used as the ability source */

	/** SetAbilitySource: 设置对象用于作为能力来源。 */
	EffectContext->SetAbilitySource(AbilitySource, SourceLevel);
	/** Sets the instigator and effect causer. Instigator is who owns the ability that spawned this, EffectCauser is the actor that is the physical source of the effect, such as a weapon. They can be the same. */

	/**
	 * AddInstigator: 
	 * 设置引发者和效果造成者。引发者是孵化这个能力的所有者，效果造成者是这个Actor的效果的物理来源，例如武器，它们是相同的。
	 */
	EffectContext->AddInstigator(Instigator, EffectCauser);
	/** Sets the object this effect was created from. */

	/** AddSourceObject: 设置效果被创造的来源对象。 */
	EffectContext->AddSourceObject(SourceObject);

	return ContextHandle;
}

void ULyraGameplayAbility::ApplyAbilityTagsToGameplayEffectSpec(FGameplayEffectSpec& Spec, FGameplayAbilitySpec* AbilitySpec) const
{
	/** Add the Ability's tags to the given GameplayEffectSpec. This is likely to be overridden per project. */

	/** ApplyAbilityTagsToGameplayEffectSpec: 添加能力标签到给定的能力玩法效果规则。这可能被每个项目覆盖。 */
	Super::ApplyAbilityTagsToGameplayEffectSpec(Spec, AbilitySpec);

	/** Returns hit result, this can be null */

	/** GetHitResult: 返回碰撞结果，能返回空。 */
	if (const FHitResult* HitResult = Spec.GetContext().GetHitResult())
	{
		/**
		 * UPhysicalMaterialWithTags: 携带标签的物理材质。
		 */

		/**
		 * Physical material that was hit.
		 * @note Must set bReturnPhysicalMaterial on the swept PrimitiveComponent or in the query params for this to be returned.
		 */

		/**
		 * PhysMaterial: 
		 * 获取碰撞的物理材质。
		 * @note 必须设置bReturnPhysicalMaterial在扫过原始组件或在请求参数中设置，最终才能被返回。
		 */
		if (const UPhysicalMaterialWithTags* PhysMatWithTags = Cast<const UPhysicalMaterialWithTags>(HitResult->PhysMaterial.Get()))
		{
			/** Tags from the target, captured during execute */

			/** CapturedTargetTags: 获取在执行期间捕获的目标节点标签。 */

			/** Get tags that came from the effect spec */

			/** GetSpecTags: 从效果规则中获取标签。 */
			Spec.CapturedTargetTags.GetSpecTags().AppendTags(PhysMatWithTags->Tags);
		}
	}
}

bool ULyraGameplayAbility::DoesAbilitySatisfyTagRequirements(const UAbilitySystemComponent& AbilitySystemComponent, const FGameplayTagContainer* SourceTags, const FGameplayTagContainer* TargetTags, OUT FGameplayTagContainer* OptionalRelevantTags) const
{
	// Specialized version to handle death exclusion and AbilityTags expansion via ASC

	// 特定版本去处理死亡排除和能力标签扩展通过ASC。

	/** NOTE: 当有其他能力请求时，判断该请求是否被忽略；一种情况是其他能力激活，然后请求对这个能力产生影响，这个能力是否被阻塞或忽略请求。 */
	bool bBlocked = false;
	bool bMissing = false;

	/** Holds global data for the ability system. Can be configured per project via config file */

	/** UAbilitySystemGlobals: 拥有能力系统的全局数据。能够被配置到每个项目通过配置文件。 */
	UAbilitySystemGlobals& AbilitySystemGlobals = UAbilitySystemGlobals::Get();
	/** TryActivate failed due to being blocked by other abilities */

	/** ActivateFailTagsBlockedTag: 尝试激活失败由于被其他能力阻塞。 */
	const FGameplayTag& BlockedTag = AbilitySystemGlobals.ActivateFailTagsBlockedTag;

	/** TryActivate failed due to missing required tags */

	/** ActivateFailTagsMissingTag: 尝试激活失败由于遗失请求标签。 */
	const FGameplayTag& MissingTag = AbilitySystemGlobals.ActivateFailTagsMissingTag;

	// Check if any of this ability's tags are currently blocked

	// 检查任意能力标签当前是否被阻塞的。

	/** Returns true if any passed in tags are blocked */

	/** AreAbilityTagsBlocked: 如果任意传入的标签被阻塞，则返回True。 */

	/** This ability has these tags */

	/** AbilityTags: 这个能力所拥有的标签。 */
	if (AbilitySystemComponent.AreAbilityTagsBlocked(AbilityTags))
	{
		bBlocked = true;
	}

	const ULyraAbilitySystemComponent* LyraASC = Cast<ULyraAbilitySystemComponent>(&AbilitySystemComponent);
	static FGameplayTagContainer AllRequiredTags;
	static FGameplayTagContainer AllBlockedTags;

	/** This ability can only be activated if the activating actor/component has all of these tags */

	/** ActivationRequiredTags: 只有激活的Actor或组件有所有这些标签，此能力才能被激活。 */
	AllRequiredTags = ActivationRequiredTags;

	/** This ability is blocked if the activating actor/component has any of these tags */

	/** ActivationBlockedTags: 只有激活的Actor或组件有任意这些标签时，此能力被阻塞。 */
	AllBlockedTags = ActivationBlockedTags;

	// Expand our ability tags to add additional required/blocked tags

	// 暴露我们的能力标签去添加额外的请求或阻塞标签。
	if (LyraASC)
	{
		/** Looks at ability tags and gathers additional required and blocking tags */

		/** 寻找能力标签并且收集添加的请求的和阻塞的标签。 */
		LyraASC->GetAdditionalActivationTagRequirements(AbilityTags, AllRequiredTags, AllBlockedTags);
	}

	// Check to see the required/blocked tags for this ability

	// 检查此能力的请求或阻塞标签。
	if (AllBlockedTags.Num() || AllRequiredTags.Num())
	{
		static FGameplayTagContainer AbilitySystemComponentTags;
		
		AbilitySystemComponentTags.Reset();

		/** GetOwnedGameplayTags: 获取所属的游戏玩法标签。 */
		AbilitySystemComponent.GetOwnedGameplayTags(AbilitySystemComponentTags);

		if (AbilitySystemComponentTags.HasAny(AllBlockedTags))
		{
			if (OptionalRelevantTags && AbilitySystemComponentTags.HasTag(LyraGameplayTags::Status_Death))
			{
				// If player is dead and was rejected due to blocking tags, give that feedback

				// 如果玩家已经死亡并且由于阻塞标签而被拒绝，给出相应的反馈。
				OptionalRelevantTags->AddTag(LyraGameplayTags::Ability_ActivateFail_IsDead);
			}

			bBlocked = true;
		}

		if (!AbilitySystemComponentTags.HasAll(AllRequiredTags))
		{
			bMissing = true;
		}
	}

	if (SourceTags != nullptr)
	{
		/** This ability is blocked if the source actor/component has any of these tags */

		/** SourceBlockedTags: 如果来源actor或组件有任意这些标签，则能力被阻塞。 */

		/** This ability can only be activated if the source actor/component has all of these tags */

		/** SourceRequiredTags: 如果来源actor或组件有所有这些标签，则能力被激活。 */
		if (SourceBlockedTags.Num() || SourceRequiredTags.Num())
		{
			if (SourceTags->HasAny(SourceBlockedTags))
			{
				bBlocked = true;
			}

			if (!SourceTags->HasAll(SourceRequiredTags))
			{
				bMissing = true;
			}
		}
	}

	if (TargetTags != nullptr)
	{
		/** This ability is blocked if the target actor/component has any of these tags */

		/** TargetBlockedTags: 如果目标Actor或组件有任意这些标签，此能力将会被阻塞。 */

		/** This ability can only be activated if the target actor/component has all of these tags */

		/** TargetRequiredTags: 如果目标Actor或组件有所有这些标签，此能力才能被激活。 */
		if (TargetBlockedTags.Num() || TargetRequiredTags.Num())
		{
			if (TargetTags->HasAny(TargetBlockedTags))
			{
				bBlocked = true;
			}

			if (!TargetTags->HasAll(TargetRequiredTags))
			{
				bMissing = true;
			}
		}
	}

	if (bBlocked)
	{
		if (OptionalRelevantTags && BlockedTag.IsValid())
		{
			OptionalRelevantTags->AddTag(BlockedTag);
		}
		return false;
	}
	if (bMissing)
	{
		if (OptionalRelevantTags && MissingTag.IsValid())
		{
			OptionalRelevantTags->AddTag(MissingTag);
		}
		return false;
	}

	return true;
}

void ULyraGameplayAbility::OnPawnAvatarSet()
{
	K2_OnPawnAvatarSet();
}

void ULyraGameplayAbility::GetAbilitySource(FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, float& OutSourceLevel, const ILyraAbilitySourceInterface*& OutAbilitySource, AActor*& OutEffectCauser) const
{
	OutSourceLevel = 0.0f;
	OutAbilitySource = nullptr;
	OutEffectCauser = nullptr;

	OutEffectCauser = ActorInfo->AvatarActor.Get();

	// If we were added by something that's an ability info source, use it

	// 如果我们添加了能力信息资源，则将会使用它。
	UObject* SourceObject = GetSourceObject(Handle, ActorInfo);

	OutAbilitySource = Cast<ILyraAbilitySourceInterface>(SourceObject);
}

void ULyraGameplayAbility::TryActivateAbilityOnSpawn(const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilitySpec& Spec) const
{
	/** Activation state of this ability. This is not replicated since it needs to be overwritten locally on clients during prediction. */

	/** ActivationInfo: 这个能力的激活状态。这不是复制的，因为他需要去在预测期间被本地客户端覆盖。 */

	/** Activation status of this ability */

	/** ActivationMode: 此能力的激活状态。 */

	/** Template to store enumeration values as bytes in a type-safe way. */

	/** TEnumAsByte<T>: 存储枚举值的模板作为字节，在类型安全方式。 */
	const bool bIsPredicting = (Spec.ActivationInfo.ActivationMode == EGameplayAbilityActivationMode::Predicting);

	// Try to activate if activation policy is on spawn.

	// 如果激活权限是孵化，尝试去激活。
	if (ActorInfo && !Spec.IsActive() && !bIsPredicting && (ActivationPolicy == ELyraAbilityActivationPolicy::OnSpawn))
	{
		UAbilitySystemComponent* ASC = ActorInfo->AbilitySystemComponent.Get();
		const AActor* AvatarActor = ActorInfo->AvatarActor.Get();

		// If avatar actor is torn off or about to die, don't try to activate until we get the new one.

		// 如果化身角色是被分离或几项死亡。不要去尝试激活能力知道获取新的化身之前。

		/** If true, this actor is no longer replicated to new clients, and is "torn off" (becomes a ROLE_Authority) on clients to which it was being replicated. */

		/** GetTearOff: 如果为真，此角色不再被复制到新客户端，并且在原本已复制该角色的客户端上处于“分离”状态(变为ROLE_Authority状态)。  */
		/**
		 * NNOTE: 角色分离： 
		 * 在网络层面的角色分离中，当角色处于分离状态时，通常会减少或暂停一些非关键数据的网络同步，如角色的细节动画、某些非关键属性等，以节省网络带宽；
		 * 但角色的关键数据，如位置、生命值等可能仍会以一定的频率进行同步，以保证游戏的基本体验和逻辑正常，并非所有数据都不同步。
		 * 
		 * 角色分离是一种优化手段，目的是在不影响游戏核心体验和逻辑的前提下，提高游戏的性能和网络效率；
		 * 通常不会使角色的所有信息都完全不同步，而是有选择性地对一些非关键信息进行处理，以达到平衡优化和游戏体验的效果。
		 */

		/** Get the remaining lifespan of this actor. If zero is returned the actor lives forever. */

		/** GetLifeSpan: 获取此Actor的剩余生存事件。如果为0，此Actor将会死亡。 */
		if (ASC && AvatarActor && !AvatarActor->GetTearOff() && (AvatarActor->GetLifeSpan() <= 0.0f))
		{
			/** How does an ability execute on the network. Does a client "ask and predict", "ask and wait", "don't ask (just do it)". */

			/** NetExecutionPolicy: 一个能力在网络上怎么执行。 */
			const bool bIsLocalExecution = (NetExecutionPolicy == EGameplayAbilityNetExecutionPolicy::LocalPredicted) || (NetExecutionPolicy == EGameplayAbilityNetExecutionPolicy::LocalOnly);
			const bool bIsServerExecution = (NetExecutionPolicy == EGameplayAbilityNetExecutionPolicy::ServerOnly) || (NetExecutionPolicy == EGameplayAbilityNetExecutionPolicy::ServerInitiated);

			const bool bClientShouldActivate = ActorInfo->IsLocallyControlled() && bIsLocalExecution;
			const bool bServerShouldActivate = ActorInfo->IsNetAuthority() && bIsServerExecution;

			if (bClientShouldActivate || bServerShouldActivate)
			{
				ASC->TryActivateAbility(Spec.Handle);
			}
		}
	}
}

bool ULyraGameplayAbility::CanChangeActivationGroup(ELyraAbilityActivationGroup NewGroup) const
{
	if (!IsInstantiated() || !IsActive())
	{
		return false;
	}

	if (ActivationGroup == NewGroup)
	{
		return true;
	}

	ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponentFromActorInfo();
	check(LyraASC);

	if ((ActivationGroup != ELyraAbilityActivationGroup::Exclusive_Blocking) && LyraASC->IsActivationGroupBlocked(NewGroup))
	{
		// This ability can't change groups if it's blocked (unless it is the one doing the blocking).

		// 如果提示被阻塞的这能力不能改变组(除非它就是那个正在做阻塞的能力)。
		return false;
	}

	if ((NewGroup == ELyraAbilityActivationGroup::Exclusive_Replaceable) && !CanBeCanceled())
	{
		// This ability can't become replaceable if it can't be canceled.

		// 如果它不能被取消，这个能力不能被替换。
		return false;
	}

	return true;
}

bool ULyraGameplayAbility::ChangeActivationGroup(ELyraAbilityActivationGroup NewGroup)
{
	ENSURE_ABILITY_IS_INSTANTIATED_OR_RETURN(ChangeActivationGroup, false);

	if (!CanChangeActivationGroup(NewGroup))
	{
		return false;
	}

	if (ActivationGroup != NewGroup)
	{
		ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponentFromActorInfo();
		check(LyraASC);

		LyraASC->RemoveAbilityFromActivationGroup(ActivationGroup, this);
		LyraASC->AddAbilityToActivationGroup(NewGroup, this);

		ActivationGroup = NewGroup;
	}

	return true;
}

void ULyraGameplayAbility::SetCameraMode(TSubclassOf<ULyraCameraMode> CameraMode)
{
	ENSURE_ABILITY_IS_INSTANTIATED_OR_RETURN(SetCameraMode, );

	if (ULyraHeroComponent* HeroComponent = GetHeroComponentFromActorInfo())
	{
		HeroComponent->SetAbilityCameraMode(CameraMode, CurrentSpecHandle);
		ActiveCameraMode = CameraMode;
	}
}

void ULyraGameplayAbility::ClearCameraMode()
{
	ENSURE_ABILITY_IS_INSTANTIATED_OR_RETURN(ClearCameraMode, );

	if (ActiveCameraMode)
	{
		if (ULyraHeroComponent* HeroComponent = GetHeroComponentFromActorInfo())
		{
			HeroComponent->ClearAbilityCameraMode(CurrentSpecHandle);
		}

		ActiveCameraMode = nullptr;
	}
}

